package com.archetypus.projectschedule.common;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.jdom.DataConversionException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import com.archetypus.projectschedule.common.exceptions.ProjectSchedulerException;

public class ResourcesTable {

	private static ResourcesTable instance;

	private Map<String, Resource> resources;

	private ResourcesTable() throws ProjectSchedulerException {
		SAXBuilder saxBuilder = new SAXBuilder();
		Document documentXML;
		resources = new HashMap<String, Resource>();
		try {
			String xmlResources = Configuration.getInstance().get("realPath")
					+ "WEB-INF/ActionFlow.xml";
			documentXML = saxBuilder.build(xmlResources);
			Iterator<?> resourcesListIter = documentXML.getRootElement()
					.getChildren().iterator();

			// Obtiene los elementos CLASS
			while (resourcesListIter.hasNext()) {
				Element element = (Element) resourcesListIter.next();
				navigateNode(element, element.getAttributeValue("id"));
			}
		} catch (Exception e) {
			throw new ProjectSchedulerException(e);
		}
	}

	public synchronized static ResourcesTable getInstance()
			throws ProjectSchedulerException {
		if (instance == null) {
			instance = new ResourcesTable();
		}
		return instance;
	}

	private void navigateNode(Element resourceNode, String fatherKey)
			throws DataConversionException {

		Element element = null;
		Iterator<?> baseIterador = null;
		String key = null;
		Resource resource = null;

		// Obtiene los elementos ACTION asociados a un CLASS
		baseIterador = resourceNode.getChildren("action").iterator();
		// Iterator<?> targetElemIter = null;
		while (baseIterador.hasNext()) {
			element = (Element) baseIterador.next();

			// construyendo clave ID del ACTION
			key = fatherKey + "." + element.getAttributeValue("id");
			navigateNode(element, key);
		}

		// Obtener los TARGET-ELEMENTS del ACTION
		baseIterador = resourceNode.getChildren("target-element").iterator();
		while (baseIterador.hasNext()) {
			element = (Element) baseIterador.next();
			// Resource del flujo normal
			resource = new Resource();
			// construyendo clave ORDER del TARGET-ELEMENT
			key = fatherKey + "." + element.getAttributeValue("order");
			resource.setKey(key);
			resource.setPath(element.getAttributeValue("path"));
			resource.setCommand(element.getAttributeValue("type").equals(
					"command"));

			// Adicionar el recurso a la tabla.
			resources.put(key, resource);
		}

		// Obtiene los elementos ALTERNATE-FLOW del TARGET-ELEMENT
		baseIterador = resourceNode.getChildren("alternate-flow").iterator();
		// Iterator<?> targetElemIter = null;
		while (baseIterador.hasNext()) {
			element = (Element) baseIterador.next();

			// construyendo clave ID del ALTERNATE-FLOW
			key = fatherKey + "." + element.getAttributeValue("id");
			navigateNode(element, key);
		}

		// Obtener los ALTERNATE-FLOW-ELEM del ALTERNATE-FLOW
		baseIterador = resourceNode.getChildren("alternate-flow-elem").iterator();
		while (baseIterador.hasNext()) {
			element = (Element) baseIterador.next();
			// Resource del flujo alterno
			resource = new Resource();
			// construyendo clave ORDER del ALTERNATE-FLOW-ELEMENT
			key = fatherKey + "." + element.getAttributeValue("order");
			resource.setKey(key);
			resource.setPath(element.getAttributeValue("path"));
			resource.setCommand(element.getAttributeValue("type").equals(
					"command"));

			// Adicionar el recurso a la tabla.
			resources.put(key, resource);
		}
	}

	public Resource getResource(String key) {
		return resources.get(key);
	}

	public Map<String, Resource> getResources() {
		return resources;
	}
}
